package com.xiaoka.flutter_plugin_gdmap.AMap;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.location.Location;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;

import androidx.annotation.NonNull;

import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.LatLonPoint;
import com.amap.api.services.route.BusRouteResult;
import com.amap.api.services.route.DriveRouteResult;
import com.amap.api.services.route.RideRouteResult;
import com.amap.api.services.route.RouteSearch;
import com.amap.api.services.route.WalkRouteResult;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.xiaoka.flutter_plugin_gdmap.Constant;
import com.xiaoka.flutter_plugin_gdmap.LittleUtils;
import com.xiaoka.flutter_plugin_gdmap.R;
import com.xiaoka.flutter_plugin_gdmap.overlay.DrivingRouteOverlay;

import java.util.ArrayList;
import java.util.List;

import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView;
import me.leefeng.promptlibrary.PromptDialog;

/**
 * Copyright (C), 2020 - 2999, Sichuan Xiaoka Technology Co., Ltd.
 *
 * @Description:地图控件
 * @Author: lch
 * @Date: 2020/10/23 16:36
 **/
public class AMapPluginView implements PlatformView, MethodChannel.MethodCallHandler {

    private final Context context;
    private final AMapBean mapBean;

    private MethodChannel mChannel;

    //地图视图
    private TextureMapView mMapView;

    //初始化地图控制器对象
    AMap aMap;

    //当前位置
    LatLng latLng = null;

    private UiSettings mUiSettings;//定义一个UiSettings对象
    private MyLocationStyle myLocationStyle;
    private RouteSearch routeSearch;
    private DrivingRouteOverlay drivingRouteOverlay;//导航路线图层类

    private PromptDialog promptDialog;//加载Dialog

    List<SortMarkerEntity> newSortList;
    List<LatLng> newLatLngs;

    String selectNum;//选中的标号

    public AMapPluginView(BinaryMessenger binaryMessenger, Activity activity, int viewId, Context context, AMapBean aMapBean) {

        this.context = context;
        promptDialog = new PromptDialog(activity);
        selectNum = "0";
        mapBean = aMapBean;
        mChannel = new MethodChannel(binaryMessenger, Constant.AMAP_CHANNEL_NAME + "/map" + viewId);
        mChannel.setMethodCallHandler(this);

        mMapView = new TextureMapView(context);
        mMapView.setBackgroundColor(Color.WHITE);
        Log.e("地图~~~~~~~~~~", "创建地图");
        mMapView.onCreate(null);//重要
        if (aMap == null) {
            aMap = mMapView.getMap();
        }

        //地图模式可选类型：MAP_TYPE_NORMAL(白昼地图（即普通地图）),MAP_TYPE_SATELLITE(卫星图),MAP_TYPE_NIGHT(夜景地图),MAP_TYPE_NAVI(导航地图)
        aMap.setMapType(AMap.MAP_TYPE_NORMAL);
        aMap.setTrafficEnabled(true);// 显示实时交通状况
        aMap.setMyLocationEnabled(true);// 设置为true表示启动显示定位蓝点，false表示隐藏定位蓝点并不进行定位，默认是false。

        /**定位蓝点**/
        myLocationStyle = new MyLocationStyle();//初始化定位蓝点样式类myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE)
        // ;//连续定位、且将视角移动到地图中心点，定位点依照设备方向旋转，并且会跟随设备移动。（1秒1次定位）如果不设置myLocationType，默认也会执行此种模式。
        myLocationStyle.interval(3000); //设置连续定位模式下的定位间隔，只在连续定位模式下生效，单次定位模式下不会生效。单位为毫秒。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);//连续定位、蓝点不会移动到地图中心点，并且蓝点会跟随设备移动。
        myLocationStyle.showMyLocation(mapBean.isShowMyLocation()); //设置是否显示定位小蓝点，用于满足只想使用定位，不想使用定位小蓝点的场景，设置false
        // 以后图面上不再有定位蓝点的概念，但是会持续回调位置信息。
        myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.common_icon_location_blue));//自定义定位蓝点图标
        myLocationStyle.anchor(0.5f, 0.5f);//自定义定位蓝点图标的锚点
        myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));// 设置圆形的边框颜色 这个颜色透明即不显示精度圆圈
        myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));// 设置圆形的填充颜色 这个颜色透明即不显示精度圆圈
        aMap.setMyLocationStyle(myLocationStyle);//设置定位蓝点的Style

        /**控件交互**/
        mUiSettings = aMap.getUiSettings();//实例化UiSettings类对象
        mUiSettings.setZoomControlsEnabled(false);//是否允许显示缩放按钮
        mUiSettings.setCompassEnabled(false);//指南针
        mUiSettings.setMyLocationButtonEnabled(mapBean.isMyLocationButtonEnabled()); //显示默认的定位按钮
        mUiSettings.setScaleControlsEnabled(false); //控制比例尺控件是否显示

        /**调用方法交互**/
        CameraUpdate mCameraUpdate = CameraUpdateFactory.zoomTo(mapBean.getZoomTo());//缩放等级
        aMap.animateCamera(mCameraUpdate);

        aMap.addOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {
            @Override
            public void onMyLocationChange(Location location) {
                //从location对象中获取经纬度信息，地址描述信息
//                Log.e("地图～～～～～", "定位：" + location.getLatitude() + "～～～" + location.getLongitude());
                latLng = new LatLng(location.getLatitude(), location.getLongitude());
            }
        });

        // 定义 Marker 点击事件监听
        AMap.OnMarkerClickListener markerClickListener = new AMap.OnMarkerClickListener() {
            // marker 对象被点击时回调的接口
            // 返回 true 则表示接口已响应事件，否则返回false
            @Override
            public boolean onMarkerClick(Marker marker) {
                Log.e("地图～～～～～", "点击marker：" + marker.getTitle());

                if (!selectNum.equals("0") && selectNum.equals(marker.getTitle())) {
                    Log.e("地图～～～～～", marker.getTitle() + "已是选中状态");
                    return false;
                }
                selectNum = marker.getTitle();

                mChannel.invokeMethod("clickMarker", marker.getTitle());

                SortMarkerEntity entity = null;
                aMap.clear();
                for (int i = 0; i < newSortList.size(); i++) {
                    if (!marker.getTitle().equals(newSortList.get(i).numSort + "")) {
                        addSortMarker(new LatLng(newSortList.get(i).latitude, newSortList.get(i).longitude), newSortList.get(i).numSort);
                    } else {
                        entity = newSortList.get(i);
                    }
                }
                //规划
                try {
                    routePlanByRouteSearch(
                            latLng,
                            newLatLngs,
                            newLatLngs.get(newLatLngs.size() - 1)
                    );
                } catch (AMapException e) {
                    e.printStackTrace();
                }

                LatLng mylatLng = new LatLng(entity.latitude, entity.longitude);
                addSortMarker2(mylatLng, entity.numSort, entity.ticketNumber, entity.phone, entity.address);
                aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mylatLng, 13));
                return false;
            }
        };
        // 绑定 Marker 被点击事件
        aMap.setOnMarkerClickListener(markerClickListener);
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
        Log.e("地图~~~~~~~~~~", "插件接收到通信Method:" + call.method);

        if (call.method.equals("changeList")) {
            //更改线路顺序
            String listJson = call.argument("list").toString();
            if (latLng == null) {
                latLng = new Gson().fromJson(call.argument("location").toString(), LatLng.class);
            }
            List<SortMarkerEntity> sortList = new Gson().fromJson(listJson, new TypeToken<List<SortMarkerEntity>>() {
            }.getType());
            List<LatLng> latLngs = new ArrayList<>();
            newSortList = sortList;
            newLatLngs = new ArrayList<>();

            selectNum = "0";

            aMap.clear();
            for (int i = 0; i < sortList.size(); i++) {
                addSortMarker(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude), sortList.get(i).numSort);
                latLngs.add(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude));
                newLatLngs.add(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude));
            }
            //规划
            try {
                routePlanByRouteSearch(
                        latLng,
                        latLngs,
                        latLngs.get(latLngs.size() - 1)
                );
            } catch (AMapException e) {
                e.printStackTrace();
            }
            latLngs.add(latLng);
            boundsZoom(latLngs, 1);
        } else if (call.method.equals("checkPoint")) {
            //查看固定点
            String listJson = call.argument("list").toString();
            if (latLng == null) {
                latLng = new Gson().fromJson(call.argument("location").toString(), LatLng.class);
            }
            List<SortMarkerEntity> sortList = new Gson().fromJson(listJson, new TypeToken<List<SortMarkerEntity>>() {
            }.getType());
            List<LatLng> latLngs = new ArrayList<>();
            SortMarkerEntity sortMarkerEntity = new Gson().fromJson(call.argument("latLng").toString(), SortMarkerEntity.class);
            newSortList = sortList;
            newLatLngs = new ArrayList<>();

            selectNum = sortMarkerEntity.numSort + "";

            aMap.clear();
            for (int i = 0; i < sortList.size(); i++) {
                if (sortMarkerEntity.numSort != sortList.get(i).numSort) {
                    addSortMarker(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude), sortList.get(i).numSort);
                }
                latLngs.add(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude));
                newLatLngs.add(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude));
            }
            //规划
            try {
                routePlanByRouteSearch(
                        latLng,
                        latLngs,
                        latLngs.get(latLngs.size() - 1)
                );
            } catch (AMapException e) {
                e.printStackTrace();
            }

            LatLng mylatLng = new LatLng(sortMarkerEntity.latitude, sortMarkerEntity.longitude);
            addSortMarker2(mylatLng, sortMarkerEntity.numSort, sortMarkerEntity.ticketNumber, sortMarkerEntity.phone,
                    sortMarkerEntity.address);
            aMap.animateCamera(CameraUpdateFactory.changeLatLng(mylatLng));
        } else if (call.method.equals("linRun")) {
            //线路开始
            String listJson = call.argument("list").toString();
            if (latLng == null) {
                latLng = new Gson().fromJson(call.argument("location").toString(), LatLng.class);
            }
            List<SortMarkerEntity> sortList = new Gson().fromJson(listJson, new TypeToken<List<SortMarkerEntity>>() {
            }.getType());
            List<LatLng> latLngs = new ArrayList<>();

            aMap.clear();

            for (int i = 0; i < sortList.size(); i++) {
                addMarker(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude), sortList.get(i).phone);
                latLngs.add(new LatLng(sortList.get(i).latitude, sortList.get(i).longitude));
            }
            //规划
            try {
                routePlanByRouteSearch(
                        latLng,
                        null,
                        latLngs.get(latLngs.size() - 1)
                );
            } catch (AMapException e) {
                e.printStackTrace();
            }
            latLngs.add(latLng);
            boundsZoom(latLngs, 2);
        } else if (call.method.equals("setZoomTo")) {
            //设置缩放等级
            //设置地图的手势是否开启
            int num = call.argument("num");
            //以动画方式按照传入的CameraUpdate参数更新地图状态，默认动画耗时250毫秒。
            // 所以不能连续使用animateCamera方法,只是得有一定的间隔
            aMap.animateCamera(CameraUpdateFactory.zoomTo(num));
        }
        result.success(true);
    }

    @Override
    public View getView() {
        return mMapView;
    }

    @Override
    public void dispose() {
        Log.e("地图~~~~~~~~~~", "地图控件销毁");
        if (mMapView != null) {
            mMapView.onDestroy();
        }

        if (mChannel != null) {
            mChannel.setMethodCallHandler(null);
        }
    }


    /** ～～～～～～～～～～～～～～～～～以下为定制内容 start～～～～～～～～～～～～～～～～～ **/

    /**
     * 添加自定义路径规划Marker
     *
     * @param latLng 经纬度信息
     * @param num    序号标记
     */
    public void addSortMarker(LatLng latLng, int num) {
        MarkerOptions markerOption = new MarkerOptions();
        markerOption.position(latLng);
        markerOption.title(num + "");
        markerOption.infoWindowEnable(false);
        //设置Marker可拖动
        markerOption.draggable(false);
        View view = LayoutInflater.from(context).inflate(R.layout.layout_custom_maker_sort, null);

        TextView makerNumTv = view.findViewById(R.id.makerNumTv);
        makerNumTv.setText(num + "");
        markerOption.icon(BitmapDescriptorFactory.fromView(view));
        markerOption.setFlat(true);
        aMap.addMarker(markerOption);
    }

    /**
     * 添加自定义路径规划Marker2
     *
     * @param latLng       经纬度信息
     * @param num          序号标记
     * @param ticketNumber 乘车人数
     * @param phone        手机号
     * @param adddress     地址
     */
    public void addSortMarker2(LatLng latLng, int num, String ticketNumber, String phone, String adddress) {
        MarkerOptions markerOption = new MarkerOptions();
        markerOption.position(latLng);
        markerOption.title(num + "");
        markerOption.infoWindowEnable(false);
        //设置Marker可拖动
        markerOption.draggable(false);
        View view = LayoutInflater.from(context).inflate(R.layout.layout_custom_maker_address, null);

        TextView makerNumTv = view.findViewById(R.id.makerNumTv);
        TextView makerNumNameTV = view.findViewById(R.id.makerNumNameTV);
        TextView makerTicketNumTv = view.findViewById(R.id.makerTicketNumTv);
        TextView makerAddressTV = view.findViewById(R.id.makerAddressTV);
        makerNumTv.setText(num + "");
        makerNumNameTV.setText("尾号" + phone.substring(phone.length() - 4));
//        makerTicketNumTv.setText("/ " + ticketNumber + "人");
        makerTicketNumTv.setText(ticketNumber);
        makerAddressTV.setText(adddress);
        markerOption.icon(BitmapDescriptorFactory.fromView(view));
        markerOption.setFlat(true);
        aMap.addMarker(markerOption);
    }

    /**
     * 添加自定义订单操作Marker
     *
     * @param latLng 经纬度信息
     * @param phone  手机号
     */
    public void addMarker(LatLng latLng, String phone) {

        MarkerOptions markerOption = new MarkerOptions();
        markerOption.position(latLng);
        //设置Marker可拖动
        markerOption.draggable(false);
        View view = LayoutInflater.from(context).inflate(R.layout.layout_passenger_maker, null);

        TextView makerPhoneTV = view.findViewById(R.id.makerPhoneTV);
        makerPhoneTV.setText("尾号" + phone.substring(phone.length() - 4));
        markerOption.icon(BitmapDescriptorFactory.fromView(view));
        markerOption.setFlat(true);
        aMap.addMarker(markerOption);
    }


    /**
     * 路径规划
     *
     * @param start   起点
     * @param latLngs 途经点
     * @param end     终点
     */
    public void routePlanByRouteSearch(LatLng start, List<LatLng> latLngs, LatLng end) throws AMapException {
        if (start == null || end == null) {
            return;
        }
        promptDialog.showLoading("路径规划中...");
        if (routeSearch == null) {
            routeSearch = new RouteSearch(context);
            routeSearch.setRouteSearchListener(new RouteSearch.OnRouteSearchListener() {
                @Override
                public void onBusRouteSearched(BusRouteResult busRouteResult, int i) {

                }

                @Override
                public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
                    promptDialog.dismiss();
                    if (i == 1000) {
                        showPath(driveRouteResult);
                    }
                }

                @Override
                public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int i) {

                }

                @Override
                public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {

                }
            });
        }
        //开始经纬度
        LatLonPoint startPoint = new LatLonPoint(start.latitude, start.longitude);
        //结束经纬度
        LatLonPoint endPoint = new LatLonPoint(end.latitude, end.longitude);
        List<LatLonPoint> latLonPoints = new ArrayList<>();
        //经纬度转换为LatLonPoint
        if (latLngs != null && latLngs.size() != 0) {
            for (int i = 0; i < latLngs.size(); i++) {
                LatLonPoint point = new LatLonPoint(latLngs.get(i).latitude, latLngs.get(i).longitude);
                latLonPoints.add(point);
            }
        }

        //路线搜索 从xx到xx 传入开始经纬度，结束经纬度
        RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(startPoint, endPoint);
        //行车路线查询
        RouteSearch.DriveRouteQuery query = new RouteSearch.DriveRouteQuery(
                fromAndTo,
                RouteSearch.DRIVING_MULTI_STRATEGY_FASTEST_SHORTEST_AVOID_CONGESTION,
                latLonPoints,
                null,
                ""
        );
        //计算驾驶路线
        routeSearch.calculateDriveRouteAsyn(query);
    }

    public void showPath(DriveRouteResult result) {
        if (drivingRouteOverlay != null) {
            drivingRouteOverlay.removeFromMap();
        }
        drivingRouteOverlay = new DrivingRouteOverlay(
                context, aMap,
                result.getPaths().get(0), result.getStartPos()
                , result.getTargetPos(), null
        );

        drivingRouteOverlay.setIsColorfulline(false);
        drivingRouteOverlay.setNodeIconVisibility(false);//隐藏转弯的节点
        drivingRouteOverlay.addToMap();
    }

    /**
     * 区域缩放
     *
     * @type 1行程规划 2 行程中
     */
    public void boundsZoom(List<LatLng> latLngs, int type) {
        if (latLngs == null) {
            return;
        }
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (int i = 0; i < latLngs.size(); i++) {
            builder.include(latLngs.get(i));
        }
        int left = LittleUtils.dp2px(context, 50);
        int right = LittleUtils.dp2px(context, 80);
        int top = LittleUtils.dp2px(context, 120);
        int bottom = LittleUtils.dp2px(context, 170);
        aMap.animateCamera(
                CameraUpdateFactory.newLatLngBoundsRect(
                        builder.build(),
                        left,//左
                        right,//右
                        type == 1 ? left : top,//上
                        type == 1 ? left : bottom//下
                )
        );
    }


}
